package com.example.shiroplusdemo.config;

import com.example.shiroplusdemo.entity.*;
import com.example.shiroplusdemo.repository.*;
import com.example.shiroplusdemo.util.MyDES;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.ValueOperations;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * @author ：Anitaxiaofeng
 * @description：
 * @create 2018-01-07
 **/
@Slf4j
public class MyRealm extends AuthorizingRealm {
    @Autowired
    private UserRepository userRepository;

    @Autowired
    private UserRoleRepository userRoleRepository;

    @Autowired
    private RolePermissionRepository rolePermissionRepository;

    @Autowired
    private RoleRepository roleRepository;

    @Autowired
    private PermissionRepository permissionRepository;

    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    //用户登录次数计数，redisKey前缀
    private String SHIRO_LOGIN_COUNT = "shiro_login_count_";

    //用户登录是否被锁定一小时前缀
    private String SHIRO_IS_LOCK = "shiro_is_lock_";


    /**
     * 授权
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        //这是将登录者的角色与权限取出来，在与shiroconfig中配置的信息比较看是否符合访问资格
        log.info("---------权限认证开始------");
        List<String> permissionList = new ArrayList();
        List<String> roleTypeList= new ArrayList<>();
        User user = (User) principalCollection.fromRealm(getName()).iterator().next();
        Integer uid = user.getId();
        List<UserRole> userRoleList = userRoleRepository.findByUid(uid);
        for(UserRole userRole:userRoleList){
            Role role = roleRepository.findById(userRole.getRid());
            roleTypeList.add(role.getType());
            List<RolePermission> rolePermissionList = rolePermissionRepository.findByRid(userRole.getRid());
            for(RolePermission rolePermission:rolePermissionList){
                Permission permission = permissionRepository.findById(rolePermission.getPid());
                permissionList.add(permission.getName());
            }
        }
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        info.addStringPermissions(permissionList);
        info.addRoles(roleTypeList);
        return info;
    }

    /**
     * 认证
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {

        log.info("------------登录认证开始-----------");
        UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken;
        String nickname = token.getUsername();
        log.info(nickname);
        String password= String.valueOf(token.getPassword()); //token.getPassword返回的是char[]
        log.info(password);
        //访问一次，计数一次
        ValueOperations<String,String> opsForValue = stringRedisTemplate.opsForValue();
        opsForValue.increment(SHIRO_LOGIN_COUNT+nickname,1);
        //计数大于5时，设置用户被锁定一小时
        if(Integer.parseInt(opsForValue.get(SHIRO_LOGIN_COUNT+nickname))>=5){
            opsForValue.set(SHIRO_IS_LOCK+nickname,"LOCK");
            stringRedisTemplate.expire(SHIRO_IS_LOCK+nickname,1, TimeUnit.HOURS);
        }
        if("LOCK".equals(opsForValue.get(SHIRO_IS_LOCK+nickname))){
            throw new DisabledAccountException("由于密码输入错误次数大于5次，账号已经禁止登录");

        }
        //密码进行加密处理 明文为password+nickname
        String paw = password+nickname;
//        String pawDES = MyDES.encryptBasedDes(paw);
        User user = userRepository.findByNickname(nickname);
        if((!password.equals(user.getPassword()))||user==null){
//        if((!pawDES.equals(user.getPassword()))||user==null){
            throw new AccountException("账号或密码不正确");
        } else if("0".equals(user.getStatus())){
            throw new DisabledAccountException("此账号已经设置为禁止登陆");
        } else{
            //登陆成功 更新登陆时间
            user.setLastLoginTime(new Date());
            userRepository.save(user);
            opsForValue.set(SHIRO_LOGIN_COUNT+nickname,"0");
        }

        log.info("身份认证成功，用户登录:",nickname);
        return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
    }
}
